package discovery

import (
	"context"
	"encoding/json"
	"fmt"
	"go.etcd.io/etcd/api/v3/mvccpb"
	clientv3 "go.etcd.io/etcd/client/v3"
	"sen-golang-study/go_game_study/hero_story_go_server/common"
	"sen-golang-study/go_game_study/hero_story_go_server/common/log"
	"strings"
	"time"
)

type EtcdDiscovery struct {
	client         *clientv3.Client
	onServerAdd    func(*common.GameServerInfo)
	onServerRemove func(uint32)
}

func NewEtcdDiscovery(endpoints []string) *EtcdDiscovery {
	client, err := clientv3.New(clientv3.Config{
		Endpoints:   endpoints,
		DialTimeout: 5 * time.Second,
	})
	if err != nil {
		log.Error("Etcd客户端创建失败, %v", err)
		return nil
	}

	return &EtcdDiscovery{
		client: client,
	}
}

func (d *EtcdDiscovery) SetCallbacks(onAdd func(*common.GameServerInfo), onRemove func(uint32)) {
	d.onServerAdd = onAdd
	d.onServerRemove = onRemove
}

func (d *EtcdDiscovery) StartWatch() {
	watchChan := d.client.Watch(context.Background(), "hero_story.server/biz_server", clientv3.WithPrefix())

	for resp := range watchChan {
		for _, event := range resp.Events {
			switch event.Type {
			case mvccpb.PUT:
				log.Info("接收到游戏服务器心跳，%s", string(event.Kv.Value))
				var gameServerInfo common.GameServerInfo
				err := json.Unmarshal(event.Kv.Value, &gameServerInfo)
				if err != nil {
					log.Error("GameServerInfo json Unmarshal err: %v", err)
					continue
				}

				if d.onServerAdd != nil {
					d.onServerAdd(&gameServerInfo)
				}
			case mvccpb.DELETE:
				key := string(event.Kv.Key)
				if strings.HasPrefix(key, "hero_story.server/game_server_") {
					serverIDStr := strings.TrimPrefix(key, "hero_story.server/game_server_")
					var serverID uint32
					if _, err := fmt.Sscanf(serverIDStr, "%d", &serverID); err == nil {
						if d.onServerRemove != nil {
							d.onServerRemove(serverID)
						}
					}
				}
			}
		}
	}
}
